package com.cnap.service.impl;

import cn.hutool.http.HttpResponse;
import com.cnap.CnapApplicationTests;
import com.cnap.model.exception.JsonException;
import com.cnap.model.schedule.engine.CommentResultForEngine;
import com.cnap.model.schedule.engine.DeployPolicyCalcRes;
import com.cnap.model.schedule.engine.DeployPolicyDistributeReq;
import com.cnap.model.schedule.engine.DeployPolicyRequest;
import com.cnap.model.schedule.engine.DeployPolicyValidateReq;
import com.cnap.model.schedule.engine.OperateReq;
import com.cnap.model.schedule.engine.ValidateResponse;
import com.cnap.service.AlgorithmEngineService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * <类文件描述>
 *
 * @author xc
 **/
class AlgorithmEngineServiceImplTest extends CnapApplicationTests {

    @Autowired
    private AlgorithmEngineService algorithmEngineService;

    @Test
    void calculateDeployPolicy() {
        String res = "{\"code\":200,\"message\":\"部署策略计算成功\",\"data\":{\"policy\":\"load\",\"actualPolicy\":\"load\",\"indicator\":\"cpu_usage,memory_usage\",\"recommendCloud\":\"Huawei\",\"userChooseCloud\":\"Huawei\",\"algDeployClusterInfos\":[{\"name\":\"huaweicloudv-tmp\",\"providerName\":\"Huawei\",\"ip\":\"172.17.4.69\",\"innerIp\":\"172.17.4.69\",\"resourceType\":\"exist\",\"createVmInfos\":[],\"clusterDetails\":[{\"name\":null,\"flavorId\":null,\"imageId\":null,\"regionId\":\"regionId\",\"zoneId\":\"zoneid\",\"sysDiskSize\":null,\"sysDiskType\":null,\"dataDisks\":null,\"bandwidth\":null,\"vmChargeType\":null,\"chargeUnit\":null,\"chargeCount\":null,\"eipChargeType\":null,\"cloudType\":null,\"cpu\":0,\"memory\":0,\"price\":\"0\",\"priceDescribe\":\"元\",\"priceShowUnit\":\"hour\",\"code\":0,\"msg\":null}],\"code\":200,\"msg\":\"successful deployment\"},{\"name\":null,\"providerName\":\"Aliyun\",\"ip\":null,\"innerIp\":null,\"resourceType\":\"create\",\"createVmInfos\":[],\"clusterDetails\":[{\"name\":null,\"flavorId\":\"ecs.g5.xlarge\",\"imageId\":\"ubuntu_18_04_x64_20G_alibase_20220824.vhd\",\"regionId\":\"cn-zhangjiakou\",\"zoneId\":\"cn-zhangjiakou-a\",\"sysDiskSize\":100,\"sysDiskType\":\"cloud_ssd\",\"dataDisks\":null,\"bandwidth\":10,\"vmChargeType\":\"PostPaid\",\"chargeUnit\":\"Month\",\"chargeCount\":3,\"eipChargeType\":\"PayByTraffic\",\"cloudType\":\"Aliyun\",\"cpu\":4,\"memory\":16,\"price\":\"1.33\",\"priceDescribe\":\"元\",\"priceShowUnit\":\"hour\",\"code\":0,\"msg\":null}],\"code\":400,\"msg\":\"require new cluster and vm resources\"},{\"name\":null,\"providerName\":\"Tencent\",\"ip\":null,\"innerIp\":null,\"resourceType\":\"create\",\"createVmInfos\":[],\"clusterDetails\":[{\"name\":null,\"flavorId\":\"S5.LARGE8\",\"imageId\":\"img-pi0ii46r\",\"regionId\":\"ap-beijing\",\"zoneId\":\"ap-beijing-3\",\"sysDiskSize\":100,\"sysDiskType\":\"CLOUD_SSD\",\"dataDisks\":null,\"bandwidth\":10,\"vmChargeType\":\"POSTPAID_BY_HOUR\",\"chargeUnit\":\"Month\",\"chargeCount\":3,\"eipChargeType\":\"TRAFFIC_POSTPAID_BY_HOUR\",\"cloudType\":\"Tencent\",\"cpu\":4,\"memory\":8,\"price\":\"0.66\",\"priceDescribe\":\"元\",\"priceShowUnit\":\"hour\",\"code\":0,\"msg\":null}],\"code\":400,\"msg\":\"require new cluster and vm resources\"}]}}";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(true);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        DeployPolicyRequest deployPolicyRequest = Mockito.mock(DeployPolicyRequest.class);
        Mockito.when(deployPolicyRequest.transToJsonStr()).thenReturn("null");
        CommentResultForEngine<DeployPolicyCalcRes> result = algorithmEngineService.calculateDeployPolicy(deployPolicyRequest);

        Assertions.assertNotNull(result);
    }

    @Test
    void calculateDeployPolicyWithoutOK() {
        String res = "{\n" +
                "  \"code\": 200,\n" +
                "  \"data\": {\n" +
                "    \"clusters\": [\n" +
                "      {\n" +
                "        \"name\": \"cluster1\",\n" +
                "        \"providerName\": \"私有云\"\n" +
                "      },\n" +
                "      {\n" +
                "        \"name\": \"cluster2\",\n" +
                "        \"providerName\": \"私有云\"\n" +
                "      }\n" +
                "    ]\n" +
                "  },\n" +
                "  \"message\": \"执行成功\"\n" +
                "}";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(false);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        DeployPolicyRequest deployPolicyRequest = Mockito.mock(DeployPolicyRequest.class);
        Mockito.when(deployPolicyRequest.transToJsonStr()).thenReturn("null");


        Assertions.assertThrows(JsonException.class, () -> {
            algorithmEngineService.calculateDeployPolicy(deployPolicyRequest);
        });
    }

    @Test
    void calculateDeployPolicyWithJsonParseNull() {
        String res = "{\n" +
                "  \"code\": 200,\n" +
                "  \"data\": {\n" +
                "    \"clusters\": [\n" +
                "      {\n" +
                "        \"name\": \"cluster1\",\n" +
                "        \"providerName\": \"私有云\"\n" +
                "      },\n" +
                "      {\n" +
                "        \"name\": \"cluster2\",\n" +
                "        \"providerName\": \"私有云\"\n" +
                "      }\n" +
                "    ]\n" +
                "  },\n" +
                "  \"message\": \"执行成功\"\n" +
                "";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(true);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        DeployPolicyRequest deployPolicyRequest = Mockito.mock(DeployPolicyRequest.class);
        Mockito.when(deployPolicyRequest.transToJsonStr()).thenReturn("null");


        Assertions.assertThrows(JsonException.class, () -> {
            algorithmEngineService.calculateDeployPolicy(deployPolicyRequest);
        });
    }

    @Test
    void calculateDeployPolicyWithCode500() {
        String res = "{\n" +
                "  \"code\": 500,\n" +
                "  \"data\": {\n" +
                "    \"clusters\": [\n" +
                "      {\n" +
                "        \"name\": \"cluster1\",\n" +
                "        \"providerName\": \"私有云\"\n" +
                "      },\n" +
                "      {\n" +
                "        \"name\": \"cluster2\",\n" +
                "        \"providerName\": \"私有云\"\n" +
                "      }\n" +
                "    ]\n" +
                "  },\n" +
                "  \"message\": \"执行成功\"\n" +
                "}";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(true);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        DeployPolicyRequest deployPolicyRequest = Mockito.mock(DeployPolicyRequest.class);
        Mockito.when(deployPolicyRequest.transToJsonStr()).thenReturn("null");


        Assertions.assertThrows(JsonException.class, () -> {
            algorithmEngineService.calculateDeployPolicy(deployPolicyRequest);
        });
    }

    @Test
    void validate() {
        String res = "{\"code\":200,\"data\":{\"results\":[{\"pass\":false,\"desc\":\"验证失败!\",\"cluster\":\"cluster1\",\"detail\":\"端口占用\"},{\"pass\":true,\"desc\":\"验证通过\",\"cluster\":\"cluster2\",\"detail\":\"\"}]},\"message\":\"执行成功\"}";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(true);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        DeployPolicyValidateReq deployPolicyValidateReq = Mockito.mock(DeployPolicyValidateReq.class);

        CommentResultForEngine<ValidateResponse> result = algorithmEngineService.validate(deployPolicyValidateReq);

        Assertions.assertNotNull(result);
    }

    @Test
    void validateWithoutOK() {
        String res = "{\"code\":200,\"data\":{\"results\":[{\"pass\":false,\"desc\":\"验证失败!\",\"cluster\":\"cluster1\",\"detail\":\"端口占用\"},{\"pass\":true,\"desc\":\"验证通过\",\"cluster\":\"cluster2\",\"detail\":\"\"}]},\"message\":\"执行成功\"}";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(false);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        DeployPolicyValidateReq deployPolicyValidateReq = Mockito.mock(DeployPolicyValidateReq.class);

        Assertions.assertThrows(JsonException.class, () -> {
            algorithmEngineService.validate(deployPolicyValidateReq);
        });
    }
    @Test
    void validateWithCode500() {
        String res = "{\"code\":500,\"data\":{\"results\":[{\"pass\":false,\"desc\":\"验证失败!\"," +
                "\"cluster\":\"cluster1\",\"detail\":\"端口占用\"},{\"pass\":true,\"desc\":\"验证通过\",\"cluster\":\"cluster2\",\"detail\":\"\"}]},\"message\":\"执行成功\"}";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(true);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        DeployPolicyValidateReq deployPolicyValidateReq = Mockito.mock(DeployPolicyValidateReq.class);

        Assertions.assertThrows(JsonException.class, () -> {
            algorithmEngineService.validate(deployPolicyValidateReq);
        });
    }


    @Test
    void validateWithJsonParseNull() {
        String res = "\"code\":200,\"data\":{\"results\":[{\"pass\":false,\"desc\":\"验证失败!\",\"cluster\":\"cluster1\",\"detail\":\"端口占用\"},{\"pass\":true,\"desc\":\"验证通过\",\"cluster\":\"cluster2\",\"detail\":\"\"}]},\"message\":\"执行成功\"}";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(true);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        DeployPolicyValidateReq deployPolicyValidateReq = Mockito.mock(DeployPolicyValidateReq.class);

        Assertions.assertThrows(JsonException.class, () -> {
            algorithmEngineService.validate(deployPolicyValidateReq);
        });
    }

    @Test
    void distribute() {
        String res = "{\"code\":200,\"data\":{\"results\":[{\"pass\":false,\"desc\":\"部署失败!\",\"cluster\":\"cluster1\",\"detail\":\"端口占用\"},{\"pass\":true,\"desc\":\"部署成功\",\"cluster\":\"cluster2\",\"detail\":\"\"}]},\"message\":\"执行成功\"}";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(true);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        DeployPolicyDistributeReq deployPolicyDistributeReq = Mockito.mock(DeployPolicyDistributeReq.class);
        Mockito.when(deployPolicyDistributeReq.transToJson()).thenReturn("null");
        CommentResultForEngine<ValidateResponse> result = algorithmEngineService.distribute(deployPolicyDistributeReq);

        Assertions.assertNotNull(result);
    }

    @Test
    void distributeWithoutOK() {
        String res = "{\"code\":200,\"data\":{\"results\":[{\"pass\":false,\"desc\":\"部署失败!\",\"cluster\":\"cluster1\",\"detail\":\"端口占用\"},{\"pass\":true,\"desc\":\"部署成功\",\"cluster\":\"cluster2\",\"detail\":\"\"}]},\"message\":\"执行成功\"}";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(false);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        DeployPolicyDistributeReq deployPolicyDistributeReq = Mockito.mock(DeployPolicyDistributeReq.class);
        Mockito.when(deployPolicyDistributeReq.transToJson()).thenReturn("null");

        Assertions.assertThrows(JsonException.class, () -> {
            algorithmEngineService.distribute(deployPolicyDistributeReq);
        });
    }

    @Test
    void distributeWithCode500() {
        String res = "{\"code\":500,\"data\":{\"results\":[{\"pass\":false,\"desc\":\"部署失败!\"," +
                "\"cluster\":\"cluster1\",\"detail\":\"端口占用\"},{\"pass\":true,\"desc\":\"部署成功\",\"cluster\":\"cluster2\",\"detail\":\"\"}]},\"message\":\"执行成功\"}";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(true);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        DeployPolicyDistributeReq deployPolicyDistributeReq = Mockito.mock(DeployPolicyDistributeReq.class);
        Mockito.when(deployPolicyDistributeReq.transToJson()).thenReturn("null");

        Assertions.assertThrows(JsonException.class, () -> {
            algorithmEngineService.distribute(deployPolicyDistributeReq);
        });
    }

    @Test
    void distributeWithJsonError() {
        String res = "\"code\":200,\"data\":{\"results\":[{\"pass\":false,\"desc\":\"部署失败!\",\"cluster\":\"cluster1\",\"detail\":\"端口占用\"},{\"pass\":true,\"desc\":\"部署成功\",\"cluster\":\"cluster2\",\"detail\":\"\"}]},\"message\":\"执行成功\"}";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(true);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        DeployPolicyDistributeReq deployPolicyDistributeReq = Mockito.mock(DeployPolicyDistributeReq.class);
        Mockito.when(deployPolicyDistributeReq.transToJson()).thenReturn("null");

        Assertions.assertThrows(JsonException.class, () -> {
            algorithmEngineService.distribute(deployPolicyDistributeReq);
        });
    }

    @Test
    void operate() {
        String res = "{\"code\":200,\"data\":{\"results\":[{\"pass\":false,\"desc\":\"部署失败!\",\"cluster\":\"cluster1\",\"detail\":\"端口占用\"},{\"pass\":true,\"desc\":\"部署成功\",\"cluster\":\"cluster2\",\"detail\":\"\"}]},\"message\":\"执行成功\"}";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(true);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        OperateReq op = Mockito.mock(OperateReq.class);

        CommentResultForEngine<Void> result = algorithmEngineService.operate(op);

        Assertions.assertNotNull(result);
    }

    @Test
    void operateWithoutOK() {
        String res = "{\"code\":200,\"data\":{\"results\":[{\"pass\":false,\"desc\":\"部署失败!\",\"cluster\":\"cluster1\",\"detail\":\"端口占用\"},{\"pass\":true,\"desc\":\"部署成功\",\"cluster\":\"cluster2\",\"detail\":\"\"}]},\"message\":\"执行成功\"}";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(false);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        OperateReq op = Mockito.mock(OperateReq.class);


        Assertions.assertThrows(JsonException.class, () -> {
            algorithmEngineService.operate(op);
        });
    }

    @Test
    void operateWithCode500() {
        String res = "{\"code\":500,\"data\":{\"results\":[{\"pass\":false,\"desc\":\"部署失败!\"," +
                "\"cluster\":\"cluster1\",\"detail\":\"端口占用\"},{\"pass\":true,\"desc\":\"部署成功\",\"cluster\":\"cluster2\",\"detail\":\"\"}]},\"message\":\"执行成功\"}";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(true);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        OperateReq op = Mockito.mock(OperateReq.class);


        Assertions.assertThrows(JsonException.class, () -> {
            algorithmEngineService.operate(op);
        });
    }

    @Test
    void operateWithJsonError() {
        String res = "1\"code\":200,\"data\":{\"results\":[{\"pass\":false,\"desc\":\"部署失败!\"," +
                "\"cluster\":\"cluster1\",\"detail\":\"端口占用\"},{\"pass\":true,\"desc\":\"部署成功\",\"cluster\":\"cluster2\",\"detail\":\"\"}]},\"message\":\"执行成功\"}";
        HttpResponse response = Mockito.mock(HttpResponse.class);
        Mockito.when(response.isOk()).thenReturn(true);
        Mockito.when(response.body()).thenReturn(res);

        Mockito.when(mockRequest.execute()).thenReturn(response);

        OperateReq op = Mockito.mock(OperateReq.class);


        Assertions.assertThrows(JsonException.class, () -> {
            algorithmEngineService.operate(op);
        });
    }
}